package com.zzyl.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageBean;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliyunIotProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.vo.DevicePropertyStatusVo;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import com.zzyl.vo.QueryThingModelVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
public class DeviceServiceImpl implements DeviceService {

    final StringRedisTemplate stringRedisTemplate;
    final AliyunIotProperties aliyunIotProperties;
    final Client client;
    final DeviceMapper deviceMapper;

    /**
     * 从物联网平台同步产品列表
     */
    @Override
    public void syncProductList2Redis() {
//        1.从阿里云IOT平台获取产品列表
        QueryProductListRequest request = new QueryProductListRequest();
        request.setCurrentPage(1);  //当前页码
        request.setPageSize(100);   // 每页条数
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());       //IOT实例ID

        QueryProductListResponse response;
        try {
            response = client.queryProductList(request);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

//        返回数据为假，调用失败
        if(!response.body.success){
            throw new BaseException(BasicEnum.IOT_LIST_PRODUCT_ERROR);
        }


        // 2. 解析返回结果，并将产品列表存入Redis
        String json = JSON.toJSONString(response.body.data.list.productInfo);
        stringRedisTemplate.opsForValue().set(CacheConstants.IOT_ALL_PRODUCT, json);
    }


    /**
     * 获取所有产品列表
     *
     * @return
     */
    @Override
    public List<ProductVo> getAllProductList() {
//        1.从Redis拿出产品的集合
        String productListJson = stringRedisTemplate.opsForValue().get(CacheConstants.IOT_ALL_PRODUCT);
        if (StrUtil.isBlank(productListJson)) {
//            返回空集合
            return List.of();
        }

        // 2. 解析返回的JSON字符串，并将数据转化为 ProductVo集合并返回
        return JSON.parseArray(productListJson, ProductVo.class);
    }


    /**
     * 注册物联网设备
     * @param dto
     */
    @Override
    public void registerDevice(DeviceDto dto) {
//        1.注册阿里云IOT设备
        RegisterDeviceRequest request = dto.getRegisterDeviceRequest();
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
//        阿里云IOT平台注册失败就抛异常
        RegisterDeviceResponse response;
        try {
            response = client.registerDevice(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
//        阿里云IOT平台响应失败就抛异常
        if(!response.body.success){
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }

//        拿到注册成功的IotId
        String iotId = response.body.data.iotId;




//        2.数据库新增设备
        try {
            Device device = BeanUtil.toBean(dto, Device.class);
            device.setIotId(iotId);
            deviceMapper.insert(device);
        }catch (Exception e) {
//            如果数据库新增设备失败，那么就将IOT平台的设备也要删除
            DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
            deleteDeviceRequest.setIotInstanceId(aliyunIotProperties.getIotInstanceId());       // Iot实例Id (类似数据库名)
            deleteDeviceRequest.setIotId(iotId);        // 设备唯一标识IotId
            try {
                client.deleteDevice(deleteDeviceRequest);
            } catch (Exception ex) {
//                IOT平台设备删除失败
                ex.printStackTrace();
                log.error("【注册设备】 - 删除阿里云设备失败：{}",ex.toString());
                throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
            }
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }

    }


    /**
     * 查询物联网设备列表
     *
     * @param dto
     * @return deviceVo
     */
    @Override
    public PageBean<DeviceVo> pageQueryDevice(DevicePageQueryDto dto) {
//        1.设置分页参数
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        // 1. 查询数据库中的设备列表
        Page<DeviceVo> page = deviceMapper.selectPage(dto);
        // 2. 转换成 Vo 并返回
        return PageBean.of(page,DeviceVo.class);
    }


    /**
     * 查询物联网设备详情
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public DeviceVo queryDeviceDetail(DeviceDto dto) {
//        1.先查询数据库中的设备表
        DeviceVo deviceVo = deviceMapper.selectByIotId(dto.getIotId());


//        2.再查询IOT平台的设备信息
        QueryDeviceDetailRequest request = new QueryDeviceDetailRequest();
        request.setIotId(dto.getIotId());
        request.setProductKey(dto.getProductKey());
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
        QueryDeviceDetailResponse response;
        try {
            response = client.queryDeviceDetail(request);
        }catch (Exception e){
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }

//        3.两种信息合并 (记住response是请求，数据封装在data里面)
        BeanUtil.copyProperties(response.body.data,deviceVo);

        return deviceVo;
    }


    /**
     * 查询设备的物模型属性状态
     *
     * @param dto
     * @return
     */
    @Override
    public DevicePropertyStatusVo queryDevicePropertyStatus(DeviceDto dto) {
        // 1. 查询IOT平台的物模型属性状态
        QueryDevicePropertyStatusRequest request = new QueryDevicePropertyStatusRequest();
        request.setDeviceName(dto.getDeviceName());
        request.setProductKey(dto.getProductKey());
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
        QueryDevicePropertyStatusResponse response;
        try {
            response = client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }
        if (!response.body.success) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }

        // 2. 转换并返回
        DevicePropertyStatusVo devicePropertyStatusVo = BeanUtil.toBean(response.body.data, DevicePropertyStatusVo.class);

//        3.前端只做了心率，所以后端要将心率信息默认排到首位
        CollUtil.sort(devicePropertyStatusVo.list.propertyStatusInfo, (o1, o2) -> StrUtil.equals(o1.getIdentifier(),"HeartRate") ? -1 : 1);

        return devicePropertyStatusVo;

    }

    /**
     * 修改设备备注名称
     *
     * @param dto
     */
    @Override
    public void updateDevice(DeviceDto dto) {
//        1.修改数据库设备的名称
        Device device = BeanUtil.toBean(dto, Device.class);
        deviceMapper.updateByPrimaryKeySelective(device);


//        2.修改IOT平台设备名称  (IOT实例ID，IOT设备名称集合【里面包含IotId和要修改的名称】）
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());

//        将dto对象装成目标对象
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo nicknameInfo =
                BeanUtil.toBean(dto, BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo.class);
//        要啥参数给他传
        request.setDeviceNicknameInfo(List.of(nicknameInfo));


        try {
            client.batchUpdateDeviceNickname(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }
    }

    /**
     * 删除物联网设备
     *
     * @param dto
     */
    @Override
    @Transactional
    public void deleteDevice(DeviceDto dto) {
//        1.删除数据库设备
        deviceMapper.deleteByIotId(dto.getIotId());

//        2.删除IOT平台设备
        DeleteDeviceRequest request = new DeleteDeviceRequest();
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
        request.setIotId(dto.getIotId());
        request.setProductKey(dto.getProductKey());
        try {
            client.deleteDevice(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }


    }

    /**
     * 查询已发布的产品模型信息
     *
     * @param request
     * @return
     */
    @Override
    public QueryThingModelVo queryThingModelPublished(QueryThingModelPublishedRequest request) {
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
        QueryThingModelPublishedResponse response;
        try {
            response = client.queryThingModelPublished(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
        }
        if(!response.body.success){
            throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
        }
        // 2. 转换并返回
        return BeanUtil.toBean(response.body.data,QueryThingModelVo.class);
    }


}
